class EventEmitter {
    constructor() {
        this._events = Object.create(null)
        // {
        //     'a': [fn, fn1, fn2 ...],
        //     'b': [fn, fn1, fn2 ...]
        // }
    }
    /**
     *订阅消息（同一消息，可订阅多个事件）
     * 
     * @param {*} evt 订阅的消息名称
     * @param {*} fn  订阅该消息，一旦发布该消息，回调事件会被相应触发
     * @memberof EventEmitter
     */
    on = (evt, fn) => {
        if (typeof fn !== 'function') {
            throw new TypeError('The callback must be a function')
        }
        if (!this._events[evt]) {
            this._events[evt] = [fn]
        } else {
            this._events[evt].push(fn)
        }
    }

    /**
     *发布消息
     *
     * @param {*} evt 
     * @param {*} args
     * @returns
     * @memberof EventEmitter
     */
    emit = (evt, ...args) => {
        // 如果不存在这个消息名称，则发布失败
        if (!this._events[evt]) return false
        const fns = [...this._events[evt]]
        fns.forEach(fn => {
            fn.apply(this, args)
        })
        return true
    }
    /**
     *evt 注册的消息名称
     *fn 回调函数
     * @memberof EventEmitter
     */
    once = (evt, fn) => {
        // 声明一个函数，当发布消息时，调用回调函数
        const offFn = () => {
            fn.apply(this)
            this.off(evt, offFn)
        }
        // 持有要删除的消息，当回调函数被调用时，去做删除操作
        this.on(evt, offFn)
    }
    off = (evt, fn) => {
        if (!this._events[evt]) return
        if (!fn) {
            this._events[evt] && (this._events[evt].length = 0)
        } else {
            const fns = this._events[evt]
            for (let i = 0; i < fns.length; i++) {
                if (fns[i] === fn || fns[i].fn === fn) {
                    fns.splice(i, 1)
                    break
                }
            }
        }
        return this
    }
    removeAllListeners(evt) {
        if (evt) {
            this._events[evt] && (this._events[evt].length = 0)
        } else {
            this._events = Object.create(null)
        }
    }
}
export const eventEmit = new EventEmitter()